Overview
once_cell
provides two new cell-like types, unsync::OnceCell
and sync::OnceCell
. OnceCell
might store arbitrary non-Copy
types, can be assigned to at most once and provide direct access
to the stored contents. In a nutshell, API looks roughly like this:
Note that, like with RefCell
and Mutex
, the set
method requires only a shared reference.
Because of the single assignment restriction get
can return an &T
instead of ReF<T>
or MutexGuard<T>
.
Patterns
OnceCell
might be useful for a variety of patterns.
Safe Initialization of global data
use ;
use OnceCell;
static INSTANCE: = INIT;
Lazy initialized global data
This is essentially lazy_static!
macro, but without a macro.
use ;
use OnceCell;
There are also sync::Lazy
and unsync::Lazy
convenience types and macros
to streamline this pattern:
extern crate once_cell;
use ;
use Lazy;
static GLOBAL_DATA: = sync_lazy! ;
General purpose lazy evaluation
Unlike lazy_static!
, Lazy
works with local variables.
use Lazy;
If you need a lazy field in a struct, you probably should use OnceCell
directly, because that will allow you to access self
during initialization.
use ;
use OnceCell;
Comparison with std
!Sync types |
Access Mode | Drawbacks |
---|---|---|
Cell<T> |
T |
works only with Copy types |
RefCel<T> |
RefMut<T> / Ref<T> |
may panic at runtime |
unsync::OnceCell<T> |
&T |
assignable only once |
Sync types |
Access Mode | Drawbacks |
---|---|---|
AtomicT |
T |
works only with certain Copy types |
Mutex<T> |
MutexGuard<T> |
may deadlock at runtime, may block the thread |
sync::OnceCell<T> |
&T |
assignable only once, may block the thread |
Technically, calling get_or_init
will also cause a panic or a deadlock if it recursively calls
itself. However, because the assignment can happen only once, such cases should be more rare than
equivalents with RefCell
and Mutex
.
Implementation details
Implementation is based on lazy_static
and
lazy_cell
crates and in some sense just streamlines and
unifies the APIs of those crates.
To implement a sync flavor of OnceCell
, this crates uses either ::std::sync::Once
or
::parking_lot::Once
. This is controlled by the parking_lot
feature, which is enabled by default.
When using parking_lot
, the crate is compatible with rustc 1.25.0, without parking_lot
a minimum
of 1.29.0
is required.
This crate uses unsafe.